package dvonn.game;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;

public class GameField2D {
	
	private HashMap<Integer, Place2D> gameField = new HashMap<Integer,Place2D>();
	private ArrayList<Point> allMovable = new ArrayList<Point>();
	private int width;
	private int height;

	public GameField2D(int width, int height) {
		this.width = width;
		this.height = height;
	}

	public boolean setToken(Point p, Token t) {
		if (p.x<0 || p.x >= this.width) return false;
		if (p.y<0 || p.y >= this.height) return false;
		Place2D place = new Place2D(t,p.x,p.y);
		if (gameField.containsKey(place.hashCode())) return false;
		gameField.put(place.hashCode(), place);
		return true;
	}
	
	public void doMove(Point from, Point to) {
		int hc = new Place2D(Token.DVONN,from.x,from.y).hashCode();
		Place2D source = gameField.remove(hc);
		allMovable.remove(from);
		hc = new Place2D(Token.DVONN,to.x,to.y).hashCode();
		Place2D target = gameField.get(hc);
		target.add( source );
		for (Point p : getAllNeighbours(from)) setMovable(p.x,p.y);
		//dvonnChecker();
	}
	
	private void setMovable(int x, int y) {
		int hc = new Place2D(Token.DVONN,x,y).hashCode();
		Place2D place = gameField.get(hc);
		if (place!=null) place.makeMovable();
		Point p = new Point(x,y);
		if (!allMovable.contains(p)) allMovable.add(p);
	}
	
	public Place2D getPlace(int x, int y) {
		int hc = new Place2D(Token.DVONN,x,y).hashCode();
		return gameField.get(hc);
	}
	
	public ArrayList<Point> getAllValidTargets(Point p) {
		ArrayList<Point> liste = new ArrayList<Point>();
		int hc = new Place2D(Token.DVONN,p.x,p.y).hashCode();
		Place2D place = gameField.get(hc);
		if (place==null) return liste;
		int size = place.getSize();
		if (size>=this.width) return liste;
		if (isValidTarget(p.x+size,p.y)) liste.add(new Point(p.x+size,p.y));
		if (isValidTarget(p.x-size,p.y)) liste.add(new Point(p.x-size,p.y));
		if (size<this.height) {
			if (isValidTarget(p.x,p.y+size)) liste.add(new Point(p.x,p.y+size));
			if (isValidTarget(p.x,p.y-size)) liste.add(new Point(p.x,p.y-size));
			if (isValidTarget(p.x+size,p.y+size)) liste.add(new Point(p.x+size,p.y+size));
			if (isValidTarget(p.x-size,p.y-size)) liste.add(new Point(p.x-size,p.y-size));
		}
		return liste;
	}
	
	public boolean isValidTarget(int x, int y) {
		int hc = new Place2D(Token.DVONN,x,y).hashCode();
		return gameField.containsKey(hc);
	}
	
	public ArrayList<Point> getAllNeighbours(Point p) {
		ArrayList<Point> liste = new ArrayList<Point>();
		if (isValidTarget(p.x+1,p.y)) liste.add( new Point(p.x+1,p.y));
		if (isValidTarget(p.x-1,p.y)) liste.add( new Point(p.x-1,p.y));
		if (isValidTarget(p.x+1,p.y+1)) liste.add( new Point(p.x+1,p.y+1));
		if (isValidTarget(p.x-1,p.y-1)) liste.add( new Point(p.x-1,p.y-1));
		if (isValidTarget(p.x+1,p.y+1)) liste.add( new Point(p.x+1,p.y+1));
		if (isValidTarget(p.x+1,p.y-1)) liste.add( new Point(p.x+1,p.y-1));
		return liste;
	}
	
	public void checkAllMovable() {
		allMovable = new ArrayList<Point>();
		for (int x=0; x<this.width; x++) {
			for (int y=0; y<this.height; y++) {
				if (this.getAllNeighbours(new Point(x,y)).size()<6) this.setMovable(x, y);
			}
		}
	}
	
	public int getWidth() { return this.width; }
	
	public int getHeight() { return this.height; }
	
	public Place2D getPlace(Point p) {
		int hc = new Place2D(Token.DVONN,p.x+1,p.y).hashCode();
		return gameField.get(hc);
	}

}
